package org.apache.james.mime4j.io;

import java.io.IOException;
import java.io.InputStream;
import org.apache.james.mime4j.util.ByteArrayBuffer;

public class BufferedLineReaderInputStream extends LineReaderInputStream
{
  private byte[] buffer;
  private int buflen;
  private int bufpos;
  private final int maxLineLen;

  public BufferedLineReaderInputStream(InputStream paramInputStream, int paramInt)
  {
    this(paramInputStream, paramInt, -1);
  }

  public BufferedLineReaderInputStream(InputStream paramInputStream, int paramInt1, int paramInt2)
  {
    super(paramInputStream);
    if (paramInputStream == null)
      throw new IllegalArgumentException("Input stream may not be null");
    if (paramInt1 <= 0)
      throw new IllegalArgumentException("Buffer size may not be negative or zero");
    this.buffer = new byte[paramInt1];
    this.bufpos = 0;
    this.buflen = 0;
    this.maxLineLen = paramInt2;
  }

  private void expand(int paramInt)
  {
    byte[] arrayOfByte = new byte[paramInt];
    int i = this.buflen - this.bufpos;
    if (i > 0)
      System.arraycopy(this.buffer, this.bufpos, arrayOfByte, this.bufpos, i);
    this.buffer = arrayOfByte;
  }

  public byte[] buf()
  {
    return this.buffer;
  }

  public int capacity()
  {
    return this.buffer.length;
  }

  public byte charAt(int paramInt)
  {
    if ((paramInt < this.bufpos) || (paramInt > this.buflen))
      throw new IndexOutOfBoundsException();
    return this.buffer[paramInt];
  }

  public void clear()
  {
    this.bufpos = 0;
    this.buflen = 0;
  }

  public void ensureCapacity(int paramInt)
  {
    if (paramInt > this.buffer.length)
      expand(paramInt);
  }

  public int fillBuffer()
    throws IOException
  {
    int l;
    if (this.bufpos > 0)
    {
      int i1 = this.buflen - this.bufpos;
      if (i1 > 0)
        System.arraycopy(this.buffer, this.bufpos, this.buffer, 0, i1);
      this.bufpos = 0;
      this.buflen = i1;
    }
    int i = this.buflen;
    int j = this.buffer.length - i;
    int k = this.in.read(this.buffer, i, j);
    if (k == -1)
      l = -1;
    while (true)
    {
      return l;
      this.buflen = (i + k);
      l = k;
    }
  }

  public boolean hasBufferedData()
  {
    int i;
    if (this.bufpos < this.buflen)
      i = 1;
    while (true)
    {
      return i;
      i = 0;
    }
  }

  public int indexOf(byte paramByte)
  {
    return indexOf(paramByte, this.bufpos, this.buflen - this.bufpos);
  }

  public int indexOf(byte paramByte, int paramInt1, int paramInt2)
  {
    int j;
    if ((paramInt1 < this.bufpos) || (paramInt2 < 0) || (paramInt1 + paramInt2 > this.buflen))
      throw new IndexOutOfBoundsException();
    int i = paramInt1;
    if (i < paramInt1 + paramInt2)
      if (this.buffer[i] == paramByte)
        j = i;
    while (true)
    {
      while (true)
      {
        return j;
        ++i;
      }
      j = -1;
    }
  }

  public int indexOf(byte[] paramArrayOfByte)
  {
    return indexOf(paramArrayOfByte, this.bufpos, this.buflen - this.bufpos);
  }

  public int indexOf(byte[] paramArrayOfByte, int paramInt1, int paramInt2)
  {
    int l;
    if (paramArrayOfByte == null)
      throw new IllegalArgumentException("Pattern may not be null");
    if ((paramInt1 < this.bufpos) || (paramInt2 < 0) || (paramInt1 + paramInt2 > this.buflen))
      throw new IndexOutOfBoundsException();
    if (paramInt2 < paramArrayOfByte.length)
    {
      l = -1;
      return l;
    }
    int[] arrayOfInt = new int[256];
    for (int i = 0; i < arrayOfInt.length; ++i)
      arrayOfInt[i] = (1 + paramArrayOfByte.length);
    for (int j = 0; j < paramArrayOfByte.length; ++j)
      arrayOfInt[(0xFF & paramArrayOfByte[j])] = (paramArrayOfByte.length - j);
    int k = 0;
    while (true)
    {
      label191: int i4;
      while (true)
      {
        if (k <= paramInt2 - paramArrayOfByte.length)
        {
          int i1 = paramInt1 + k;
          int i2 = 1;
          int i3 = 0;
          while (true)
          {
            while (true)
            {
              if (i3 < paramArrayOfByte.length)
              {
                if (this.buffer[(i1 + i3)] == paramArrayOfByte[i3])
                  break;
                i2 = 0;
              }
              if (i2 == 0)
                break label191;
              l = i1;
            }
            ++i3;
          }
          i4 = i1 + paramArrayOfByte.length;
          if (i4 < this.buffer.length)
            break;
        }
        l = -1;
      }
      k += arrayOfInt[(0xFF & this.buffer[i4])];
    }
  }

  public int length()
  {
    return (this.buflen - this.bufpos);
  }

  public int limit()
  {
    return this.buflen;
  }

  public boolean markSupported()
  {
    return false;
  }

  public int pos()
  {
    return this.bufpos;
  }

  public int read()
    throws IOException
  {
    do
      if (hasBufferedData())
        break label21;
    while (fillBuffer() != -1);
    int j = -1;
    while (true)
    {
      return j;
      label21: byte[] arrayOfByte = this.buffer;
      int i = this.bufpos;
      this.bufpos = (i + 1);
      j = 0xFF & arrayOfByte[i];
    }
  }

  public int read(byte[] paramArrayOfByte)
    throws IOException
  {
    int i;
    if (paramArrayOfByte == null)
      i = 0;
    while (true)
    {
      return i;
      i = read(paramArrayOfByte, 0, paramArrayOfByte.length);
    }
  }

  public int read(byte[] paramArrayOfByte, int paramInt1, int paramInt2)
    throws IOException
  {
    int j;
    if (paramArrayOfByte == null)
      j = 0;
    while (true)
    {
      while (true)
      {
        return j;
        do
          if (hasBufferedData())
            break label33;
        while (fillBuffer() != -1);
        j = -1;
      }
      label33: int i = this.buflen - this.bufpos;
      if (i > paramInt2)
        i = paramInt2;
      System.arraycopy(this.buffer, this.bufpos, paramArrayOfByte, paramInt1, i);
      this.bufpos = (i + this.bufpos);
      j = i;
    }
  }

  public int readLine(ByteArrayBuffer paramByteArrayBuffer)
    throws IOException
  {
    int l;
    if (paramByteArrayBuffer == null)
      throw new IllegalArgumentException("Buffer may not be null");
    int i = 0;
    int j = 0;
    int k = 0;
    if (j == 0)
    {
      if (hasBufferedData())
        break label63;
      k = fillBuffer();
      if (k != -1)
        break label63;
    }
    if ((i == 0) && (k == -1))
      l = -1;
    while (true)
    {
      label63: int i2;
      return l;
      int i1 = indexOf(10);
      if (i1 != -1)
      {
        j = 1;
        i2 = i1 + 1 - pos();
      }
      while (true)
      {
        do
          if (i2 > 0)
          {
            paramByteArrayBuffer.append(buf(), pos(), i2);
            skip(i2);
            i += i2;
          }
        while ((this.maxLineLen <= 0) || (paramByteArrayBuffer.length() < this.maxLineLen));
        throw new MaxLineLimitException("Maximum line length limit exceeded");
        i2 = length();
      }
      l = i;
    }
  }

  public int skip(int paramInt)
  {
    int i = Math.min(paramInt, this.buflen - this.bufpos);
    this.bufpos = (i + this.bufpos);
    return i;
  }

  public String toString()
  {
    StringBuffer localStringBuffer = new StringBuffer();
    localStringBuffer.append("[pos: ");
    localStringBuffer.append(this.bufpos);
    localStringBuffer.append("]");
    localStringBuffer.append("[limit: ");
    localStringBuffer.append(this.buflen);
    localStringBuffer.append("]");
    localStringBuffer.append("[");
    for (int i = this.bufpos; i < this.buflen; ++i)
      localStringBuffer.append((char)this.buffer[i]);
    localStringBuffer.append("]");
    return localStringBuffer.toString();
  }
}